package com.qp.basics.auth.controller;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qp.basics.auth.config.bean.SecurityProperties;
import com.qp.basics.auth.service.OnlineUserService;
import com.qp.basics.auth.service.UserCacheClean;
import com.qp.basics.common.utils.RedisUtils;
import com.qp.basics.auth.service.dto.OnlineUserDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;

import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.security.Principal;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
public class UserInfoController2 {
    @Autowired
    private OnlineUserService onlineUserService;
    @Autowired
    private SecurityProperties properties;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private UserCacheClean userCacheClean;

    /**
     * 当前的登录的用户对象
     * @param principal
     * @return
     */
    @GetMapping("/user/info")
    public Principal userInfo(Principal principal){
        // 使用ThreadLocal来实现的
//        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return principal ;
    }

    //@Log("刷新token")
    @PostMapping("/token/renew")
    public ResponseEntity renew(@RequestParam String token){
        OnlineUserDto onlineUserDto = null;
        Authentication authentication = null;
        boolean cleanUserCache = false;
        try {
            onlineUserDto = onlineUserService.getOne(properties.getOnlineKey() + token);
        } catch (Exception e) {
            log.error(e.getMessage());
            cleanUserCache = true;
        } finally {
            if (cleanUserCache || Objects.isNull(onlineUserDto)) {
                Jwt jwt = JwtHelper.decode(token);
                String jwtJsonStr = jwt.getClaims();
                JSONObject jwtJson = JSON.parseObject(jwtJsonStr);
                String name = jwtJson.getString("user_name");
                userCacheClean.cleanUserCache(name);
            }
        }
        if (onlineUserDto != null && StringUtils.hasText(token)) {
            checkRenewal(token);
        }
        return new ResponseEntity<>(HttpStatus.OK);
    }

    private void checkRenewal(String token) {
        // 判断是否续期token,计算token的过期时间
        long time = redisUtils.getExpire(properties.getOnlineKey() + token) * 1000;
        Date expireDate = DateUtil.offset(new Date(), DateField.MILLISECOND, (int) time);
        // 判断当前时间与过期时间的时间差
        long differ = expireDate.getTime() - System.currentTimeMillis();
        // 如果在续期检查的范围内，则续期
        if (differ <= properties.getDetect()) {
            long renew = time + properties.getRenew();
            redisUtils.expire(properties.getOnlineKey() + token, renew, TimeUnit.MILLISECONDS);
        }
    }
}
